<?php declare(strict_types = 1);

namespace Gnway\Ticket\Rest\Annotation;

use Doctrine\Common\Annotations\Annotation\Target;
use Doctrine\Common\Annotations\Annotation\Attribute;
use Doctrine\Common\Annotations\Annotation\Attributes;
use Gnway\Ticket\Rest\Request\RequestMethod;
use InvalidArgumentException;

/**
 * RequestMapping Annotation
 *
 * @Annotation
 * @Target("METHOD")
 * @Attributes(
 *   @Attribute("value", type="array", required=true),
 *   @Attribute("method", type="array", required=true),
 *   @Attribute("validation", type="array", required=false)
 * )
 * @author zushaolong
 * @mail zushaolong@gmail.com
 */
final class RequestMapping
{

  /**
   * Action routing path
   *
   * @var string[]
   */
  private array $value = [];

  /**
   * Routing supported HTTP method set
   *
   * @var string[]
   */
  private array $method = [];

  /**
   * Routing bind parameters validate rule
   *
   * @var array
   */
  private array $validation = [];

  /**
   * RequestMapping constructor.
   *
   * @param array $values
   */
  public function __construct(array $values)
  {
    if (isset($values['value'])) {
      $this->value = (array)$values['value'];
    }
    if (isset($values['method'])) {
      $method = (array)$values['method'];
      $allowed = array_values(RequestMethod::getConstants());
      $notAllowed = array_diff($method, $allowed);
      if (sizeof($notAllowed) > 0) {
        throw new InvalidArgumentException(sprintf(
          '@RequestMapping "method" property supports only values is %s, %s given.',
          json_encode($allowed, JSON_UNESCAPED_UNICODE),
          json_encode($notAllowed, JSON_UNESCAPED_UNICODE)
        ));
      }
      $this->method = $method;
    }
    if (isset($values['validation'])) {
      $this->validation = (array)$values['validation'];
    }
  }

  /**
   * @return string[]
   */
  public function getValue(): array
  {
    return $this->value;
  }

  /**
   * @return string[]
   */
  public function getMethod(): array
  {
    return $this->method;
  }

  /**
   * @return array
   */
  public function getValidation(): array
  {
    return $this->validation;
  }
}